#!/usr/bin/env python3
# Copyright (c) 2024 maminjie <canpool@163.com>
# SPDX-License-Identifier: MulanPSL-2.0

"""
A cli demo using cmdln.py.
"""

import importlib
import importlib.util
import inspect
import os
import sys
import traceback

from pycanpool import cmdln

builtin_plugin_dir = os.path.join(os.path.dirname(__file__), 'plugins')


class MyCLI(cmdln.Cmdln):
    """
    My cli demo.

    other messages
    """
    name = "git"

    def __init__(self):
        cmdln.Cmdln.__init__(self)
        cmdln.Cmdln.do_help.aliases.append("h")
        self.options = None
        self._load_plugins()

    @cmdln.alias("it", "ini")
    @cmdln.option("-q", "--quiet", action='store_true',
                  help='be quiet')
    @cmdln.option("--bare", action='store_true',
                  help='create a bare repository')
    @cmdln.option("--template", type=str, metavar="<template-directory>",
                  help='directory from which templates will be used')
    @cmdln.option("--shared", metavar='[<permissions>]',
                  help='specify that the git repository is to be shared amongst several users')
    def do_init(self, subcmd, opts, *args):
        """
        Create an empty Git repository or reinitialize an existing one

        other messages
        """
        print("'git %s' opts: %s" % (subcmd, opts))
        print("'git %s' args: %s" % (subcmd, args))

    def _load_plugins(self):
        plugin_dirs = [
            builtin_plugin_dir,
            '/usr/lib/git-plugins',
            '/usr/local/lib/git-plugins',
            os.path.expanduser('~/.local/lib/git-plugins'),
            os.path.expanduser('~/.git-plugins')]
        for plugin_dir in plugin_dirs:
            if not os.path.isdir(plugin_dir):
                continue
            sys.path.append(plugin_dir)
            for extfile in os.listdir(plugin_dir):
                if not extfile.endswith('.py'):
                    continue
                try:
                    modname = "git.plugins." + os.path.splitext(extfile)[0]
                    spec = importlib.util.spec_from_file_location(modname, os.path.join(plugin_dir, extfile))
                    mod = importlib.util.module_from_spec(spec)
                    sys.modules[modname] = mod
                    spec.loader.exec_module(mod)
                    # restore the old exec semantic
                    mod.__dict__.update(globals())
                    for name in dir(mod):
                        data = getattr(mod, name)
                        # Add all functions (which are defined in the imported module)
                        # to the class (filtering only methods which start with "do_"
                        # breaks the old behavior).
                        # Also add imported modules (needed for backward compatibility).
                        # New plugins should not use "self.<imported modname>.<something>"
                        # to refer to the imported module. Instead use
                        # "<imported modname>.<something>".
                        if (inspect.isfunction(data) and inspect.getmodule(data) == mod
                                or inspect.ismodule(data)):
                            setattr(self.__class__, name, data)
                except (SyntaxError, NameError, ImportError) as e:
                    if os.environ.get('GIT_PLUGIN_FAIL_IGNORE'):
                        print(f"{os.path.join(plugin_dir, extfile)}: {e}\n", file=sys.stderr)
                    else:
                        traceback.print_exc(file=sys.stderr)
                        print(f'\n{os.path.join(plugin_dir, extfile)}: {e}', file=sys.stderr)
                        print("\n Try 'env GIT_PLUGIN_FAIL_IGNORE=1 osc ...'", file=sys.stderr)
                        sys.exit(1)


if __name__ == "__main__":
    mycli = MyCLI()
    sys.exit(mycli.main())
